#include "SdkOsd.h"

#define DEF_TAG             "Osd"

#define DEF_FONT_WIDTH      16                  //default font size
#define DEF_FONT_HEIGHT     16                  //default font size
#define DEFAULT_FONT_BIN            "/system/bin/ak_font_16.bin"

Com_s32 g_SdkOsd_Status;

/* argb8888 table */
unsigned int g_SdkOsd_RGB_Color_Tables[] = {
    0x00000000, 0xffffffff, 0xff000000, 0xff0000ff,
    0xff00ff00, 0xffff0000, 0xffffff00, 0xffff00ff,
    0xff00ffff, 0xff786085, 0xff2c8aa0, 0xff68d535,
    0xff34aa5a, 0xff43e9ab, 0xff4b55a5, 0xff008080};

int SdkOsd_Create_Canvas(int chn_id,int location,int img_w,int img_h,VI_CHN_ATTR *chn_attr)
{
    ak_vi_get_chn_attr(chn_id, chn_attr);
    struct osd_canvas_info canvas = {0};

    if(location == 1)
    {
        /* first region */
        canvas.region_id = 1;
        canvas.pos_in_yuv.x = 0;          //pos x
        canvas.pos_in_yuv.y = 0;          //pos y
    }
    else if(location == 2)
    {
        /* second region */
        canvas.region_id = 1;
        canvas.pos_in_yuv.x = chn_attr->res.width - img_w;          //pos x
        canvas.pos_in_yuv.y = 0;          //pos y
    }
    else if(location == 3)
    {
        /* third region */
        canvas.region_id = 1;
        canvas.pos_in_yuv.x = 0;          //pos x
        canvas.pos_in_yuv.y = chn_attr->res.height - img_h;          //pos y
    }
    else if(location == 4)
    {
        canvas.region_id = 1;
        canvas.pos_in_yuv.x = chn_attr->res.width - img_w;          //pos x
        canvas.pos_in_yuv.y = chn_attr->res.height - img_h;          //pos y
    }

    canvas.channel_id = chn_id;
    canvas.region_size_width = img_w;   //res w
    canvas.region_size_height = img_h;  //res h
    canvas.canvas_color_index = 0;      //canvas color
    canvas.alpha = 0;
    if (AK_SUCCESS != ak_osd_create_canvas(&canvas))
    {
        ak_print_normal(MODULE_ID_APP, "ak_osd_create_canvas failed!! %d\n",__LINE__);
        return -1;
    }

    return 0;
}

void SdkOsd_Draw_Bitmap2Canvas(int chn_id,int location,int img_w,int img_h,int bit_width,unsigned char *data)
{
    /* draw the osd region 绘制osd区域*/
    struct osd_drawing_info draw = {0};
    draw.bitmap_size_height = img_h;
    draw.bitmap_size_width = img_w;
    draw.buffer_size = img_w*img_h / (8 / bit_width);
    draw.buffer = data;

    //画布(区域)ID，每个位置对应一个ID，如果有多个OSD，需要确保不同地方的OSD的ID不一样
    draw.region_id = 1;

    draw.channel_id = chn_id;
    if (AK_SUCCESS != ak_osd_draw_bitmap_to_canvas(&draw))
    {
        ak_print_normal(MODULE_ID_APP, "ak_osd_draw_bitmap_to_canvas 0 0 failed!!\n");
    }
}

void SdkOsd_Set_Logo(int location,int chn_id)
{
    int ret = 0;
    FILE *fp = NULL;
    unsigned int line_byte = 0;                 //logo bmp img line byte
    unsigned char *data = NULL;                 //logo bmp img data(yuv)
    int img_w = 0;                              //logo bmp res width
    int img_h = 0;                              //logo bmp res height
    char *p = NULL;                             //logo bmp img raw data(rgb)
    /** font color, bit_width 1 [0, 1], bit_width 2 [0, 3], bit_width 4 [0, 15], default 1 **/
    int font_color = 1;
    /** background color, bit_width 1 [0, 1], bit_width 2 [0, 3], bit_width 4 [0, 15], default 0 **/
    int bg_color = 0;
    VI_CHN_ATTR chn_attr = {0};

    /* get logo bmp info */
    if(Ext_InComFile_Access(DEF_OSD_LOGO_BMP_SUB) == DEF_COM_FILE_EXIST && chn_id == VIDEO_CHN1)
    {
        fp = fopen(DEF_OSD_LOGO_BMP_SUB, "rb");
    }
    else if(Ext_InComFile_Access(DEF_OSD_LOGO_BMP) == DEF_COM_FILE_EXIST)
    {
        fp = fopen(DEF_OSD_LOGO_BMP, "rb");
    }

    if (NULL == fp)
    {
        ak_print_normal(MODULE_ID_APP, "logo file open failed!\n");
        goto EXIT;
    }

    //bmp format
    fseek(fp, 18, SEEK_SET);
    fread(&img_w, 1, 4, fp);
    fread(&img_h, 1, 4, fp);

    ak_print_normal(MODULE_ID_APP, "img width:%d, height:%d!\n", img_w, img_h);
    data = (unsigned char *)ak_mem_alloc(MODULE_ID_APP, img_w*img_h/2);
    if (NULL == data)
    {
        ak_print_normal(MODULE_ID_APP, "data calloc fail!\n");
        goto EXIT;
    }

    /* align */
    line_byte = (img_w * 3 + 3) & ~0x3;
    /* raw bmp data(rgb888) */
    p = (char *)ak_mem_alloc(MODULE_ID_APP, line_byte*img_h);
    if (NULL == p) {
        ak_print_normal(MODULE_ID_APP, "p calloc fail!\n");
        goto EXIT;
    }

    fseek(fp, 54, SEEK_SET);
    fread(p, 1, line_byte*img_h, fp);
    fclose(fp);
    fp = NULL;

    struct osd_attr attr = {0};
    attr.color_mode_index = AK_OSD_COLOR_FMT_RGB;   //rgb mode
    attr.color_table = g_SdkOsd_RGB_Color_Tables;            //init rgb map table
    attr.region_num = 4;
    /** color type ,0 color, 1 mono, default 0 **/
    attr.color_type = 0;
    /** bit width 1, 2 ,4 , default 4 **/
    attr.bit_width = 4;

    if (AK_SUCCESS != ak_osd_init(&attr))           //osd init
    {
        ak_print_normal(MODULE_ID_APP, "ak_osd_init failed!!\n");
        goto EXIT;
    }

    ret = SdkOsd_Create_Canvas(chn_id,location,img_w,img_h,&chn_attr);
    if(ret == -1)
    {
        goto EXIT;
    }

    /* transform the rgb value to index data 将RGB值转换为索引数据*/
    if (4 == attr.bit_width)
    {
        unsigned char *dst = data + img_w * (img_h - 1) / 2;
        unsigned char r, g, b, id;
        char *tmp = p;
        for (int i=0; i<img_h; i++)
        {
            for (int j=0; j<img_w; j++)
            {
                b = *tmp;
                g = *(tmp+1);
                r = *(tmp+2);

                if (r + g + b >= 128*3)
                    id = font_color;
                else
                    id = bg_color;

                if (0 == j % 2)
                    *(dst+j/2) = id;
                else
                    *(dst+j/2) |= (id << 4);

                tmp += 3;
            }
            dst -= img_w/2;
            tmp += line_byte - img_w*3;
        }
    }
    else if (2 == attr.bit_width)
    {
        unsigned char *dst = data + img_w * (img_h - 1) / 4;
        unsigned char r, g, b, id;
        char *tmp = p;
        for (int i=0; i<img_h; i++)
        {
            for (int j=0; j<img_w; j++)
            {
                b = *tmp;
                g = *(tmp+1);
                r = *(tmp+2);

                if (r + g + b >= 128*3)
                    id = font_color;
                else
                    id = bg_color;

                if (0 == j % 4)
                    *(dst+j/4) = id;
                else if(1 == j % 4)
                    *(dst+j/4) |= (id << 2);
                else if(2 == j % 4)
                    *(dst+j/4) |= (id << 4);
                else if(3 == j % 4)
                    *(dst+j/4) |= (id << 6);

                tmp += 3;
            }
            dst -= img_w/4;
            tmp += line_byte - img_w*3;
        }
    }
    else if (1 == attr.bit_width)
    {
        unsigned char *dst = data + img_w * (img_h - 1) / 8;
        unsigned char r, g, b, id;
        char *tmp = p;
        for (int i=0; i<img_h; i++)
        {
            for (int j=0; j<img_w; j++)
            {
                b = *tmp;
                g = *(tmp+1);
                r = *(tmp+2);

                if (r + g + b >= 128*3)
                    id = font_color;
                else
                    id = bg_color;

                if (0 == j % 8)
                    *(dst+j/8) = id;
                else if(1 == j % 8)
                    *(dst+j/8) |= (id << 1);
                else if(2 == j % 8)
                    *(dst+j/8) |= (id << 2);
                else if(3 == j % 8)
                    *(dst+j/8) |= (id << 3);
                else if(4 == j % 8)
                    *(dst+j/8) |= (id << 4);
                else if(5 == j % 8)
                    *(dst+j/8) |= (id << 5);
                else if(6 == j % 8)
                    *(dst+j/8) |= (id << 6);
                else if(7 == j % 8)
                    *(dst+j/8) |= (id << 7);

                tmp += 3;
            }
            dst -= img_w/8;
            tmp += line_byte - img_w*3;
        }
    }

    SdkOsd_Draw_Bitmap2Canvas(chn_id,location,img_w,img_h,attr.bit_width,data);

    /* set to vi */
    if (AK_SUCCESS != ak_osd_set_to_vi())
    {
        ak_print_normal(MODULE_ID_APP,"ak_osd_set_to_vi failed!!\n");
    }

EXIT:
    /* release source */
    if (data)
    {
        ak_mem_free(data);
    }

    if (p)
    {
        ak_mem_free(p);
    }

    if (fp)
    {
        fclose(fp);
    }

    ak_print_normal_ex(MODULE_ID_APP, "osd set over\n");
}

void Ext_SdkOsd_Set_Status(Com_s32 flag)
{
    g_SdkOsd_Status = flag;

    if(g_SdkOsd_Status)
    {
        /* osd set logo */
        SdkOsd_Set_Logo(2,VIDEO_CHN0);
        SdkOsd_Set_Logo(2,VIDEO_CHN1);
    }
}

int Ext_SdkOsd_Clear(void)
{
    int ret = -1;
    int i;

    for (i = 0; i < 2; i++)
    {
        int width,height;
        width = 20 * (DEF_FONT_WIDTH + 2);
        height = DEF_FONT_HEIGHT * 2 + 2;

        ret = ak_osd_ex_clean_str(i, 0, 0, 0,width,height);
        if (ret != 0)
        {
            printf("ak_osd_clean_str failed\n");
            return -1;
        }

        ak_osd_clean_canvas(i,1);
    }

    return 0;
}

Com_pvoid SdkOsd_Thread(Com_pvoid arg)
{
    int i;
    int video_chn;
    int osd_chn = 0;
    char osd_string[40];
    unsigned short us_osd_string[40];
    time_t currTime;
    struct tm *currDate;

    /* osd ex test */
    ak_osd_ex_set_font_file(16, DEFAULT_FONT_BIN);
    ak_osd_ex_init();
    ak_osd_ex_set_color(1, 0);
    ak_osd_ex_set_edge_color(2);
    ak_osd_ex_set_font_size(VIDEO_CHN0, 32);
    ak_osd_ex_set_font_size(VIDEO_CHN1, 16);

    while (Ext_InComFile_Access(DEF_FLAG_SYNC_TIME_OK) == DEF_COM_FILE_NOT_EXIST)
    {
        usleep(100 * 1000);
    }

    for (video_chn = 0; video_chn < 2; video_chn++)
    {
        int width;
        int height;
        int max_w, max_h;
        /* get the rect max size */
        if (ak_osd_ex_get_max_rect(video_chn, &max_w, &max_h) < 0)
        {
            ak_print_error_ex(MODULE_ID_APP, "chn:%d ak_osd_get_max_rect fail!\n", video_chn);
            return NULL;
        }
        PRT_NORMAL("######## video_chn:%d max_w:%d  max_h:%d \n",video_chn, max_w, max_h);

        /* get the string code */
        width = 20 * (DEF_FONT_WIDTH + 2);
        height = DEF_FONT_HEIGHT * 2 + 2;

        width = (width > max_w) ? max_w : width;
        height = (height > max_h) ? max_h : height;

        osd_chn = 0;
        int x = 16;
        int y = 8;

        PRT_NORMAL("video_chn:%d osd_chn:%d X:Y:%d:%d width:%d  height:%d \n",video_chn, osd_chn,x,y, width, height);
        if (ak_osd_ex_set_rect(video_chn, osd_chn, x, y, width, height) < 0)
        {
            ak_print_error_ex(MODULE_ID_APP,"video_chn:%d ak_osd_set_rect fail!\n",video_chn);
            return NULL;
        }
    }

    DEF_COM_SET_THREAD_NAME("OSD_Thread",g_ComThread_Num);

    while(g_ComThread_Running)
    {
        if (g_SdkOsd_Status == DEF_COM_TRUE)
        {
            for (video_chn = 0; video_chn < 2; video_chn++)
            {
                memset(&currTime,0,sizeof(currTime));

                time(&currTime);
                currDate = localtime(&currTime);

                memset(osd_string, 0, sizeof(osd_string));
                memset(us_osd_string, 0, sizeof(us_osd_string));
                strftime(osd_string,40,"%Y-%m-%d %H:%M:%S",currDate);
                for (i = 0; i < strlen(osd_string); i++)
                {
                    us_osd_string[i] = osd_string[i];
                }

                osd_chn = 0;
                /* draw string */
                if (ak_osd_ex_draw_str(video_chn, osd_chn, 0, 0,us_osd_string, strlen(osd_string)) < 0)
                {
                    ak_print_error_ex(MODULE_ID_APP,"video_chn:%d ak_osd_draw_str fail!\n",video_chn);
                    break;
                }
            }
        }
        usleep(500 * 1000);
    }

    DEF_COM_EXIT_THREAD(g_ComThread_Num);
}

void Ext_SdkOsd_Init(void)
{
    pthread_t id;

    pthread_create(&id, NULL, SdkOsd_Thread,NULL);
    pthread_detach(id);
}

